package com.lzp.java.concurrent.deadlock;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.TimeUnit;

/**
 * 必然死锁案例
 *
 * @author lzp
 * @date 2020/03/02
 */
public class MustDeadLock implements Runnable {
    private int flag;

    public MustDeadLock(int flag) {
        this.flag = flag;
    }

    private static final Object resourceA = new Object();
    private static final Object resourceB = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new MustDeadLock(0));
        Thread thread2 = new Thread(new MustDeadLock(1));
        thread1.start();
        thread2.start();

        // 使用ThreadMXBean检测死锁
        Thread.sleep(1000);
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        long[] deadLockThreads = threadMXBean.findDeadlockedThreads();
        if (deadLockThreads != null && deadLockThreads.length != 0) {
            for (long deadLockThread : deadLockThreads) {
                ThreadInfo threadInfo = threadMXBean.getThreadInfo(deadLockThread);
                System.out.println("死锁线程:" + threadInfo.getThreadName());
            }
        }
    }

    @Override
    public void run() {
        if (flag == 0) {
            synchronized (resourceA) {
                System.out.println(Thread.currentThread().getName() + "获取A锁");
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (resourceB) {
                    System.out.println(Thread.currentThread().getName() + "获取B锁");
                }
            }
        } else {
            synchronized (resourceB) {
                System.out.println(Thread.currentThread().getName() + "获取B锁");
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (resourceA) {
                    System.out.println(Thread.currentThread().getName() + "获取A锁");
                }
            }
        }
    }
}
